package com.yonyou.crm.base.product.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yonyou.crm.base.attrgroup.service.AttrGroupBizServiceImpl;
import com.yonyou.crm.base.product.entity.PrdtypeVO;
import com.yonyou.crm.bpub.refervalue.entity.ReferDataVO;
import com.yonyou.crm.common.biz.service.BaseBizServiceImpl;
import com.yonyou.crm.common.enumeration.entity.EnableStateEnum;
import com.yonyou.crm.common.enumeration.service.EnumBizServiceImpl;
import com.yonyou.crm.common.exception.CrmBusinessException;
import com.yonyou.crm.common.field.handler.FieldRelationHandler;
import com.yonyou.crm.common.field.relation.EnumFieldRelation;
import com.yonyou.crm.common.field.relation.FieldRelation;
import com.yonyou.crm.common.field.relation.RefFieldRelation;
import com.yonyou.crm.common.page.entity.Page;
import com.yonyou.iuap.context.InvocationInfoProxy;

@Service
public class PrdtypeBizServiceImpl extends BaseBizServiceImpl<PrdtypeVO>{
	
	@Autowired
	private EnumBizServiceImpl enumService;
	@Autowired
	private AttrGroupBizServiceImpl agService;
	
	public List<Map<String, Object>> getTree() {
		List<Map<String, Object>> prdtypeTree = dao.selectList(PrdtypeVO.class, "findPrdtypeTree", null);
		return prdtypeTree;
	}
	
	public Page<PrdtypeVO> getPage(Page<PrdtypeVO> page, Map<String, Object> paraMap) {
		
		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", InvocationInfoProxy.getTenantid());
		
		Page<PrdtypeVO> prdtypePage = dao.pageSelect(PrdtypeVO.class, page, paraMap.keySet().toArray(new String[0]), paraMap.values().toArray());
		
		trans(prdtypePage.getData());
		
		return prdtypePage;
	}
	
	public List<PrdtypeVO> getList(Map<String, Object> paraMap){
		
		if (paraMap == null) {
			paraMap = new HashMap<String, Object>();
		}
		
		paraMap.put("tenantId", InvocationInfoProxy.getTenantid());
		
		List<PrdtypeVO> voList = dao.selectVoList(PrdtypeVO.class, "getList", paraMap);
				
		trans(voList);
		
		return voList;
	}
	
	private List<PrdtypeVO> trans(List<PrdtypeVO> prdtypeList){
		if(prdtypeList != null && prdtypeList.size() > 0) {
			List<FieldRelation<PrdtypeVO>> relations = new ArrayList<FieldRelation<PrdtypeVO>>();
			relations.add(new EnumFieldRelation<PrdtypeVO>(PrdtypeVO.class, "enableState", "enableStateName", enumService, "enable_state"));
			relations.add(new RefFieldRelation<PrdtypeVO>(PrdtypeVO.class, "attrGroupId", new String[]{"attrGroupName"}, agService, "selectFieldsByIds"));
			new FieldRelationHandler<PrdtypeVO>().handler(prdtypeList, relations);
		}
		return prdtypeList;
	}
	
	@Override
	protected void beforeSaveVO(PrdtypeVO vo) {

		super.beforeSaveVO(vo);

		String code = vo.getCode();
		String name = vo.getName();
		//校验编码唯一性
		int codeCount = getCountByCode(null, code);
		if (codeCount > 0) {
			throw new CrmBusinessException("编码和其他产品产品分类重复，保存失败。");
		}
		
		//校验名称唯一性
		int nameCount = getCountByName(null, name);
		if (nameCount > 0) {
			throw new CrmBusinessException("名称和其他产品分类重复，保存失败。");
		}
		
		if (vo.getPath() != null) {
			vo.setLevel(vo.getPath().split(",").length + 1);
		}
		
		vo.setEnableState(EnableStateEnum.ENABLE.getValue());
	}
	
	@Override
	protected void afterSaveVO(PrdtypeVO vo) {
		super.afterSaveVO(vo);
		
		trans(Arrays.asList(vo));
	}
	
	/**
	 * 批量删除
	 * @param ids
	 * @return
	 */
	public String batchDeleteByIDs(String[] ids) {
		
		if (ids == null || ids.length == 0) {
			return "";
		}
		
		Set<String> failIdSet = new HashSet<String>();
		Set<String> idSet = new HashSet<String>();
		for (String id : ids) {
			
			//获得所有子级
			List<String> subIdList = getChildIds(new Long(id));
				
			//是否被产品引用
			if (isCitedByProduct(subIdList.toArray(new String[0]))) {
				failIdSet.add(id);
			}
			else {
				idSet.addAll(subIdList);
			}
		}
		
		if (idSet.size() > 0) {
			super.batchDeleteByIDs(PrdtypeVO.class, idSet);
		}
		
		String message = null;
		int failCount = failIdSet.size();
		if (failCount > 0) {
			String name = getNamesByIds(failIdSet.toArray(new String[0]));
			message = "成功" + (ids.length - failCount) + "条,失败" + failCount + "条，"
					+ "原因：【" + name + "】该分类或该分类的末级分类被产品引用，不可删除！";
		}
		else {
			message = "删除成功";
		}
		
		return message;
	}
	
	@Override
	protected void beforeUpdateVO(PrdtypeVO vo) {

		super.beforeUpdateVO(vo);
		
		String code = vo.getCode();
		Long id = vo.getId();
		String name = vo.getName();
		//校验编码唯一性
		int codeCount = getCountByCode(id, code);
		if (codeCount > 0) {
			throw new CrmBusinessException("编码和其他产品分类重复，保存失败。");
		}
		
		//校验名称唯一性
		int nameCount = getCountByName(id, name);
		if (nameCount > 0) {
			throw new CrmBusinessException("名称和其他产品分类重复，保存失败。");
		}
	}
	
	@Override
	protected void afterUpdateVO(PrdtypeVO vo) {
		super.afterUpdateVO(vo);
		
		trans(Arrays.asList(vo));
	}
	
	/**
	 * 详情
	 * @param id
	 * @return
	 */
	public PrdtypeVO getDetailById(Long id){
		PrdtypeVO vo = super.getVOById(PrdtypeVO.class, id);
		trans(Arrays.asList(vo));
		return vo;
	}
	
	/*
	 * 获取参照档案列表
	 */
	public List<ReferDataVO> getRefervalues(Page<PrdtypeVO> page, Map<String, Object> paraMap) {
		// TODO 加权限
		Page<PrdtypeVO> pageVO = dao.pageSelect(PrdtypeVO.class, page, "selectRefervalues", "countRefervalues", paraMap);
		List<PrdtypeVO> voList = pageVO.getData();
		
		List<ReferDataVO> rsList = new ArrayList<ReferDataVO>();
		for (PrdtypeVO vo : voList) {
			ReferDataVO referDataVO = new ReferDataVO();
			referDataVO.setId(vo.getId().toString());
			referDataVO.setValue(vo.getName());
			
			rsList.add(referDataVO);
		}
		return rsList;
	}
	
	/*
	 * 获取参照档案列表
	 */
	public List<PrdtypeVO> getRefervaluesForApp(Page<PrdtypeVO> page, Map<String, Object> paraMap) {
		// TODO 加权限
		Page<PrdtypeVO> pageVO = dao.pageSelect(PrdtypeVO.class, page, "selectRefervalues", "countRefervalues", paraMap);
		List<PrdtypeVO> voList = pageVO.getData();
		return voList;
	}
	
	/**
	 * 参照树
	 * @param paraMap
	 * @return
	 */
	public List<Map<String, Object>> getRefTree(Map<String, Object> paraMap) {
		return dao.selectList(PrdtypeVO.class, "getRefTree", paraMap);
	}
	
	public Object selectFieldsByIds(Object[] ids) {
		Map<String, Object> para = new HashMap<String, Object>();
		para.put("ids", ids);
		return dao.selectList(PrdtypeVO.class, "selectFieldsByIds", para);
	}
	
	/**
	 * 根据编码查询数量
	 * @param id
	 * @param code
	 * @return
	 */
	public int getCountByCode(Long id, String code) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("id", id);
		paraMap.put("code", code);
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		return dao.countAll(PrdtypeVO.class, "getCountByCode", paraMap);
	}
	
	/**
	 * 根据名称查询数量
	 * @param id
	 * @param name
	 * @return
	 */
	public int getCountByName(Long id, String name) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("id", id);
		paraMap.put("name", name);
		paraMap.put("tenantId", new Long(InvocationInfoProxy.getTenantid()));
		return dao.countAll(PrdtypeVO.class, "getCountByName", paraMap);
	}
	
	/**
	 * 批量停启用
	 * 停用，停用该级及所有下级
	 * 启用，启用该级及所有上级
	 * @param ids
	 * @param enableState
	 */
	public void batchUpdateEnableState(String[] ids, Integer enableState) {
		
		if (ids == null || ids.length == 0) {
			return;
		}
		
		Map<String, Object> paraMap = new HashMap<String, Object>();
		Set<String> idSet = new HashSet<String>();
		
		if (enableState.intValue() == EnableStateEnum.ENABLE.getValue()) {
			
			//获得所有上级
			idSet.addAll(getFatherIds(ids));
			//添加本级
			for (String id : ids) {
				idSet.add(id);
			}
			
			paraMap.put("enableUserId", new Long(InvocationInfoProxy.getParameter("id")));
			paraMap.put("enableTime", new Date());
		}
		else {
			
			//获得所有子级
			for (String id : ids) {
				idSet.addAll(getChildIds(new Long(id)));
			}
			
			paraMap.put("disableUserId", new Long(InvocationInfoProxy.getParameter("id")));
			paraMap.put("disableTime", new Date());	

		}

		paraMap.put("ids", idSet);
		paraMap.put("enableState", enableState);
		
		if (idSet.size() > 0) {
			dao.updateSql(PrdtypeVO.class, "batchUpdateEnableState", paraMap);
		}
	}
	
	/**
	 * 获得所有子级分类及本分类
	 * @param ids
	 * @return
	 */
	private List<String> getChildIds(Long id) {
		return dao.selectStrList(PrdtypeVO.class, "getChildIds", id);
	}
	
	/**
	 * 获得所有父级分类
	 * @param ids
	 * @return
	 */
	private List<String> getFatherIds(String[] ids) {
		
		List<String> fatherIdList = new ArrayList<String>();
		String fatherIdStr = (String)dao.selectOne(PrdtypeVO.class, "getFatherIds", ids);
		if (StringUtils.isNoneBlank(fatherIdStr)) {
			
			String[] fatherIds = fatherIdStr.split(",");
			for (String fatherId : fatherIds) {
				
				if (!fatherIdList.contains(fatherId)) {
					fatherIdList.add(fatherId);
				}
			}
		}
		return fatherIdList;
	}
	
	/**
	 * 是否被产品引用
	 * @param prdtypeIds
	 * @return
	 */
	private boolean isCitedByProduct(String[] prdtypeIds) {
		return dao.countAll(PrdtypeVO.class, "getPrdCountByIds", prdtypeIds) > 0;
	}
	
	/**
	 * 根据id获得名称
	 * @param prdtypeIds
	 * @return
	 */
	private String getNamesByIds(String[] prdtypeIds) {
		return (String)dao.selectOne(PrdtypeVO.class, "getNamesByIds", prdtypeIds);
	}
}
